#include "widget.h"
#include "ui_widget.h"
#include "logqueue.h"
#include "screen.h"
#include "chatmessage.h"
#include <QMessageBox>
#include <QSoundEffect>
#include <QScrollBar>
#include <QRegularExpression>
#include <QRegularExpressionValidator>

extern LogQueue *logqueue;

QRect Widget::pos = QRect(-1, -1, -1, -1);

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    logqueue = new LogQueue();
    logqueue->start();

    qDebug() << "main: " << QThread::currentThread();
    qRegisterMetaType<MSG_TYPE*>("MSG_TYPE*");
    qRegisterMetaType<MSG_TYPE>("MSG_TYPE");

    WRITE_LOG("-------------------------Application Start---------------------------");
    WRITE_LOG("main UI thread id: 0x%p", QThread::currentThreadId());

    //UI界面
    _createmeet = false;
    _openCamera = false;
    _joinmeet = false;
    Widget::pos = QRect(0.1 * screen::width, 0.1 * screen::height, 0.8 * screen::width, 0.8 * screen::height);

    ui->setupUi(this);

    this->setGeometry(Widget::pos);
    this->setMinimumSize(QSize(Widget::pos.width() * 0.7, Widget::pos.height() * 0.7));
    this->setMaximumSize(QSize(Widget::pos.width(), Widget::pos.height()));

    ui->exitmeetBtn->setDisabled(true);
    ui->joinmeetBtn->setDisabled(true);
    ui->createmeetBtn->setDisabled(true);
    ui->openAudio->setDisabled(true);
    ui->openVideo->setDisabled(true);
    ui->sendmsg->setDefault(true);
    mainip = 0;

    //创建传输视频帧线程
    _sendImg = new SendImg();
    _imgThread = new QThread();
    _sendImg->moveToThread(_imgThread);

    connect(_imgThread, &QThread::started, _sendImg, &SendImg::run);
    connect(_imgThread, &QThread::finished, _sendImg, &SendImg::clearImgQueue);
    _imgThread->start();

    //tcp传输数据处理
    _mytcpSocket = new MyTcpSocket();
    connect(_mytcpSocket, &MyTcpSocket::sendTextOver, this, &Widget::textSend);

    //文本传输
    _sendText = new SendText();
    _textThread = new QThread();
    _sendText->moveToThread(_textThread);
    connect(_textThread, &QThread::started, _sendText, &SendText::run);
    connect(this, &Widget::PushText, _sendText, &SendText::push_Text);
    _textThread->start();

    _captureSession = new QMediaCaptureSession(this);//创建会话
    //配置摄像头
    _camera = new QCamera(this);
    //出错处理
    connect(_camera, &QCamera::errorOccurred, this, &Widget::cameraError);
    _imagecapture = new QImageCapture(this);
    _myvideosurface = new MyVideoSurface(this);
    _captureSession->setCamera(_camera);
    _captureSession->setImageCapture(_imagecapture);
    _captureSession->setVideoSink(_myvideosurface);
    connect(_myvideosurface, &MyVideoSurface::frameAvailable, this, &Widget::cameraImageCapture);
    connect(this, &Widget::pushImg, _sendImg, &SendImg::pushToQueue);
    //_camera->start();

    //接收数据线程
    _recvThread = new RecvSolve();
    connect(_recvThread, &RecvSolve::datarecv, this, &Widget::datasolve, Qt::BlockingQueuedConnection);
    _recvThread->start();

    //音频
    _ainput = new AudioInput();
    _ainputThread = new QThread();
    _ainput->moveToThread(_ainputThread);

    _aoutput = new AudioOutput();
    _ainputThread->start(); //获取音频，发送
    _aoutput->start(); //播放

    connect(this, &Widget::startAudio, _ainput, &AudioInput::startCollect);
    connect(this, &Widget::stopAudio, _ainput, &AudioInput::stopCollect);
    connect(_ainput, &AudioInput::audioinputerror, this, &Widget::audioError);
    connect(_aoutput, &AudioOutput::audiooutputerror, this, &Widget::audioError);
    connect(_aoutput, &AudioOutput::speaker, this, &Widget::speaks);

    //设置滚动条
    ui->scrollArea->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width:8px; background:rgba(0,0,0,0%); margin:0px,0px,0px,0px; padding-top:9px; padding-bottom:9px; } QScrollBar::handle:vertical { width:8px; background:rgba(0,0,0,25%); border-radius:4px; min-height:20; } QScrollBar::handle:vertical:hover { width:8px; background:rgba(0,0,0,50%); border-radius:4px; min-height:20; } QScrollBar::add-line:vertical { height:9px;width:8px; border-image:url(:/images/a/3.png); subcontrol-position:bottom; } QScrollBar::sub-line:vertical { height:9px;width:8px; border-image:url(:/images/a/1.png); subcontrol-position:top; } QScrollBar::add-line:vertical:hover { height:9px;width:8px; border-image:url(:/images/a/4.png); subcontrol-position:bottom; } QScrollBar::sub-line:vertical:hover { height:9px;width:8px; border-image:url(:/images/a/2.png); subcontrol-position:top; } QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical { background:rgba(0,0,0,10%); border-radius:4px; }");
    ui->listWidget->setStyleSheet("QScrollBar:vertical { width:8px; background:rgba(0,0,0,0%); margin:0px,0px,0px,0px; padding-top:9px; padding-bottom:9px; } QScrollBar::handle:vertical { width:8px; background:rgba(0,0,0,25%); border-radius:4px; min-height:20; } QScrollBar::handle:vertical:hover { width:8px; background:rgba(0,0,0,50%); border-radius:4px; min-height:20; } QScrollBar::add-line:vertical { height:9px;width:8px; border-image:url(:/images/a/3.png); subcontrol-position:bottom; } QScrollBar::sub-line:vertical { height:9px;width:8px; border-image:url(:/images/a/1.png); subcontrol-position:top; } QScrollBar::add-line:vertical:hover { height:9px;width:8px; border-image:url(:/images/a/4.png); subcontrol-position:bottom; } QScrollBar::sub-line:vertical:hover { height:9px;width:8px; border-image:url(:/images/a/2.png); subcontrol-position:top; } QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical { background:rgba(0,0,0,10%); border-radius:4px; }");

    QFont te_font = this->font();
    te_font.setFamily("MicrosoftYaHei");
    te_font.setPointSize(12);

    ui->listWidget->setFont(te_font);

    ui->tabWidget->setCurrentIndex(1);
    ui->tabWidget->setCurrentIndex(0);
}

Widget::~Widget(){
    //终止底层发送与接收线程

    if(_mytcpSocket->isRunning()){
        _mytcpSocket->stopImmediately();
        _mytcpSocket->quit();
        _mytcpSocket->wait();
    }

    //终止接收处理线程
    if(_recvThread->isRunning()){
        _recvThread->stopImmediately();
        _recvThread->quit();
        _recvThread->wait();
    }

    if(_imgThread->isRunning())
    {
        _imgThread->quit();
        _imgThread->wait();
    }

    _sendImg->stopImmediately();
    _sendImg->deleteLater();
    _imgThread->quit();
    _imgThread->wait();


    if(_textThread->isRunning()){
        _textThread->quit();
        _textThread->wait();
    }


    _sendText->stopImmediately();
    _sendText->deleteLater();
    _textThread->quit();
    _textThread->wait();


    if (_ainputThread->isRunning()){
        _ainputThread->quit();
        _ainputThread->wait();
    }

    if (_aoutput->isRunning()){
        _aoutput->stopImmediately();
        _aoutput->quit();
        _aoutput->wait();
    }
    WRITE_LOG("-------------------Application End-----------------");

    //关闭日志
    if(logqueue->isRunning()){
        logqueue->stopImmediately();
        logqueue->wait();
    }
    delete ui;
}

void Widget::textSend(){
    qDebug() << "send text over";
    QListWidgetItem *lastItem = ui->listWidget->item(ui->listWidget->count() - 1);
    ChatMessage* messageW = (ChatMessage *)ui->listWidget->itemWidget(lastItem);
    messageW->setTextSuccess();
    ui->sendmsg->setDisabled(false);
}

void Widget::cameraError(QCamera::Error error, const QString & errstr){
    qDebug() << error;
    QMessageBox::warning(this, errstr, _camera->errorString() , QMessageBox::Yes, QMessageBox::Yes);
}

void Widget::cameraImageCapture(QVideoFrame frame){
    qDebug() << "cameraImageCapture";
    if(frame.isValid() && frame.isReadable()){
        QImage videoImg = frame.toImage();
        QTransform matmix;
        matmix.scale(-1,1);

        QImage img = videoImg.transformed(matmix, Qt::FastTransformation).scaled(ui->mainshow_label->size());
        //ui->mainshow_label->setPixmap(QPixmap::fromImage(img));
        if(partner.size() > 1){
            emit pushImg(img);
        }
        if(_mytcpSocket->getlocalip() == mainip){
            ui->mainshow_label->setPixmap(QPixmap::fromImage(img).scaled(ui->mainshow_label->size()));
        }
        Partner *p = partner[_mytcpSocket->getlocalip()];
        if(p) p->setpic(img);
    }
    frame.unmap();
}

void Widget::datasolve(MESG *msg){
    if(msg->msg_type == CREATE_MEETING_RESPONSE){
        int roomno;
        memcpy(&roomno, msg->data, msg->len);
        if(roomno){
            QMessageBox::information(this, "Room No", QString("房间号：%1").arg(roomno), QMessageBox::Yes, QMessageBox::Yes);

            ui->groupBox_2->setTitle(QString("主屏幕(房间号: %1)").arg(roomno));
            ui->outlog->setText(QString("创建成功 房间号: %1").arg(roomno));
            _createmeet = true;
            ui->exitmeetBtn->setDisabled(false);
            ui->openVideo->setDisabled(false);
            ui->joinmeetBtn->setDisabled(true);

            WRITE_LOG("succeed creating room %d", roomno);
            //添加用户自己
            addPartner(_mytcpSocket->getlocalip());
            mainip = _mytcpSocket->getlocalip();
            ui->groupBox_2->setTitle(QHostAddress(mainip).toString());
            ui->mainshow_label->setPixmap(QPixmap::fromImage(QImage(":/myImage/1.jpg").scaled(ui->mainshow_label->size())));
        }else{
            _createmeet = false;
            QMessageBox::information(this, "Room Information", QString("无可用房间"), QMessageBox::Yes, QMessageBox::Yes);
            ui->outlog->setText(QString("无可用房间"));
            ui->createmeetBtn->setDisabled(false);
            WRITE_LOG("no empty room");
        }
    }else if(msg->msg_type == JOIN_MEETING_RESPONSE){
        qint32 c;
        memcpy(&c, msg->data, msg->len);
        if(c == 0){
            QMessageBox::information(this, "Meeting Error", tr("会议不存在") , QMessageBox::Yes, QMessageBox::Yes);
            ui->outlog->setText(QString("会议不存在"));
            WRITE_LOG("meeting not exist");
            ui->exitmeetBtn->setDisabled(true);
            ui->openVideo->setDisabled(true);
            ui->joinmeetBtn->setDisabled(false);
            ui->connServer->setDisabled(true);
            _joinmeet = false;
        }else if(c == -1){
            QMessageBox::warning(this, "Meeting information", "成员已满，无法加入" , QMessageBox::Yes, QMessageBox::Yes);
            ui->outlog->setText(QString("成员已满，无法加入"));
            WRITE_LOG("full room, cannot join");
        }else if (c > 0){
            QMessageBox::warning(this, "Meeting information", "加入成功" , QMessageBox::Yes, QMessageBox::Yes);
            ui->outlog->setText(QString("加入成功"));
            WRITE_LOG("succeed joining room");
            //添加用户自己
            addPartner(_mytcpSocket->getlocalip());
            mainip = _mytcpSocket->getlocalip();
            ui->groupBox_2->setTitle(QHostAddress(mainip).toString());
            ui->mainshow_label->setPixmap(QPixmap::fromImage(QImage(":/myImage/1.jpg").scaled(ui->mainshow_label->size())));
            ui->joinmeetBtn->setDisabled(true);
            ui->exitmeetBtn->setDisabled(false);
            ui->createmeetBtn->setDisabled(true);
            _joinmeet = true;
        }
    }else if(msg->msg_type == IMG_RECV){
        QHostAddress a(msg->ip);
        qDebug() << a.toString();
        QImage img;
        img.loadFromData(msg->data, msg->len);
        if(partner.count(msg->ip) == 1){
            Partner* p = partner[msg->ip];
            p->setpic(img);
        }else{
            Partner* p = addPartner(msg->ip);
            p->setpic(img);
        }

        if(msg->ip == mainip){
            ui->mainshow_label->setPixmap(QPixmap::fromImage(img).scaled(ui->mainshow_label->size()));
        }
        repaint();
    }else if(msg->msg_type == TEXT_RECV){
        QString str = QString::fromStdString(std::string((char *)msg->data, msg->len));
        //qDebug() << str;
        QString time = QString::number(QDateTime::currentSecsSinceEpoch());
        ChatMessage *message = new ChatMessage(ui->listWidget);
        QListWidgetItem *item = new QListWidgetItem();
        dealMessageTime(time);
        dealMessage(message, item, str, time, QHostAddress(msg->ip).toString() ,ChatMessage::User_She);
        if(str.contains('@' + QHostAddress(_mytcpSocket->getlocalip()).toString())){
            QSoundEffect effect;
            effect.setSource(QUrl(":/myEffect/2.wav"));
            effect.play();
        }
    }else if(msg->msg_type == PARTNER_JOIN){
        Partner* p = addPartner(msg->ip);
        if(p){
            p->setpic(QImage(":/myImage/1.jpg"));
            ui->outlog->setText(QString("%1 join meeting").arg(QHostAddress(msg->ip).toString()));
            iplist.append(QString("@") + QHostAddress(msg->ip).toString());
            //增加补全功能
            ui->plainTextEdit->setCompleter(iplist);
        }
    }else if(msg->msg_type == PARTNER_EXIT){
        removePartner(msg->ip);
        if(mainip == msg->ip){
            ui->mainshow_label->setPixmap(QPixmap::fromImage(QImage(":/myImage/1.jpg").scaled(ui->mainshow_label->size())));
        }
        if(iplist.removeOne(QString("@") + QHostAddress(msg->ip).toString())){
            ui->plainTextEdit->setCompleter(iplist);
        }else{
            qDebug() << QHostAddress(msg->ip).toString() << "not exist";
            WRITE_LOG("%s not exist",QHostAddress(msg->ip).toString().toStdString().c_str());
        }
        ui->outlog->setText(QString("%1 exit meeting").arg(QHostAddress(msg->ip).toString()));
    }else if (msg->msg_type == CLOSE_CAMERA){
        closeImg(msg->ip);
    }else if(msg->msg_type == PARTNER_JOIN2){
        uint32_t ip;
        int other = msg->len / sizeof(uint32_t), pos = 0;
        for (int i = 0; i < other; i++){
            memcpy_s(&ip, sizeof(uint32_t), msg->data + pos , sizeof(uint32_t));
            pos += sizeof(uint32_t);
            Partner* p = addPartner(ip);
            if (p)
            {
                p->setpic(QImage(":/myImage/1.jpg"));
                iplist << QString("@") + QHostAddress(ip).toString();
            }
        }
        ui->plainTextEdit->setCompleter(iplist);
        ui->openVideo->setDisabled(false);
    }else if(msg->msg_type == RemoteHostClosedError){
        clearPartner();
        _mytcpSocket->disconnectFromHost();
        _mytcpSocket->wait();
        ui->outlog->setText(QString("关闭与服务器的连接"));
        ui->createmeetBtn->setDisabled(true);
        ui->exitmeetBtn->setDisabled(true);
        ui->connServer->setDisabled(false);
        ui->joinmeetBtn->setDisabled(true);
        //清除聊天记录
        while(ui->listWidget->count() > 0){
            QListWidgetItem *item = ui->listWidget->takeItem(0);
            ChatMessage *chat = (ChatMessage *)ui->listWidget->itemWidget(item);
            delete item;
            delete chat;
        }
        iplist.clear();
        ui->plainTextEdit->setCompleter(iplist);
        if(_createmeet || _joinmeet) QMessageBox::warning(this, "Meeting Information", "会议结束" , QMessageBox::Yes, QMessageBox::Yes);
    }else if(msg->msg_type == OtherNetError){
        QMessageBox::warning(NULL, "Network Error", "网络异常" , QMessageBox::Yes, QMessageBox::Yes);
        clearPartner();
        _mytcpSocket->disconnectFromHost();
        _mytcpSocket->wait();
        ui->outlog->setText(QString("网络异常......"));
    }
    if(msg->data){
        free(msg->data);
        msg->data = nullptr;
    }
    if(msg){
        free(msg);
        msg = nullptr;
    }
}

Partner* Widget::addPartner(quint32 ip){
    if (partner.contains(ip)) return nullptr;
    Partner *p = new Partner(ui->scrollAreaWidgetContents ,ip);
    if (p == nullptr){
        qDebug() << "new Partner error";
        return nullptr;
    }else{
        connect(p, &Partner::sendip, this, &Widget::recvip);
        partner.insert(ip, p);
        ui->verticalLayout_7->addWidget(p, 1);

        //当有人员加入时，开启滑动条滑动事件，开启输入(只有自己时，不打开)
        if (partner.size() > 1){
            connect(this, &Widget::volumnChange, _ainput, &AudioInput::setVolumn, Qt::UniqueConnection);
            connect(this,  &Widget::volumnChange, _aoutput,&AudioOutput::setVolumn, Qt::UniqueConnection);
            ui->openAudio->setDisabled(false);
            ui->sendmsg->setDisabled(false);
            _aoutput->startPlay();
        }
        return p;
    }
}

void Widget::recvip(quint32 ip){
    if (partner.contains(mainip)){
        Partner* p = partner[mainip];
        p->setStyleSheet("border-width: 1px; border-style: solid; border-color:rgba(0, 0 , 255, 0.7)");
    }
    if (partner.contains(ip)){
        Partner* p = partner[ip];
        p->setStyleSheet("border-width: 1px; border-style: solid; border-color:rgba(255, 0 , 0, 0.7)");
    }
    ui->mainshow_label->setPixmap(QPixmap::fromImage(QImage(":/myImage/1.jpg").scaled(ui->mainshow_label->size())));
    mainip = ip;
    ui->groupBox_2->setTitle(QHostAddress(mainip).toString());
    qDebug() << ip;
}

void Widget::audioError(QString err)
{
    QMessageBox::warning(this, "Audio error", err, QMessageBox::Yes);
}

void Widget::speaks(QString ip)
{
    ui->outlog->setText(QString(ip + " 正在说话").toUtf8());
}

void Widget::dealMessageTime(QString curMsgTime){
    bool isShowTime = false;
    if(ui->listWidget->count() > 0) {
        QListWidgetItem* lastItem = ui->listWidget->item(ui->listWidget->count() - 1);
        ChatMessage* messageW = (ChatMessage *)ui->listWidget->itemWidget(lastItem);
        int lastTime = messageW->time().toInt();
        int curTime = curMsgTime.toInt();
        qDebug() << "curTime lastTime:" << curTime - lastTime;
        isShowTime = ((curTime - lastTime) > 60); // 两个消息相差一分钟
    } else {
        isShowTime = true;
    }
    if(isShowTime) {
        ChatMessage* messageTime = new ChatMessage(ui->listWidget);
        QListWidgetItem* itemTime = new QListWidgetItem();
        ui->listWidget->addItem(itemTime);
        QSize size = QSize(ui->listWidget->width() , 40);
        messageTime->resize(size);
        itemTime->setSizeHint(size);
        messageTime->setText(curMsgTime, curMsgTime, size);
        ui->listWidget->setItemWidget(itemTime, messageTime);
    }
}

void Widget::dealMessage(ChatMessage *messageW, QListWidgetItem *item, QString text, QString time, QString ip ,ChatMessage::User_Type type){
    ui->listWidget->addItem(item);
    messageW->setFixedWidth(ui->listWidget->width());
    QSize size = messageW->fontRect(text);
    item->setSizeHint(size);
    messageW->setText(text, time, size, ip, type);
    ui->listWidget->setItemWidget(item, messageW);
}

void Widget::removePartner(quint32 ip){
    if(partner.contains(ip)){
        Partner *p = partner[ip];
        disconnect(p, &Partner::sendip, this, &Widget::recvip);
        ui->verticalLayout_7->removeWidget(p);
        delete p;
        partner.remove(ip);

        //只有自已一个人时，关闭传输音频
        if (partner.size() <= 1){
            disconnect(_ainput, SLOT(setVolumn(int)));
            disconnect(_aoutput, SLOT(setVolumn(int)));
            _ainput->stopCollect();
            _aoutput->stopPlay();
            ui->openAudio->setText(QString(OPENAUDIO).toUtf8());
            ui->openAudio->setDisabled(true);
        }
    }
}

void Widget::closeImg(quint32 ip){
    if (!partner.contains(ip)){
        qDebug() << "close img error";
        return;
    }
    Partner * p = partner[ip];
    p->setpic(QImage(":/myImage/1.jpg"));

    if(mainip == ip){
        ui->mainshow_label->setPixmap(QPixmap::fromImage(QImage(":/myImage/1.jpg").scaled(ui->mainshow_label->size())));
    }
}

void Widget::clearPartner(){
    ui->mainshow_label->setPixmap(QPixmap());
    if(partner.size() == 0) return;

    QMap<quint32, Partner*>::iterator iter =   partner.begin();
    while (iter != partner.end()){
        quint32 ip = iter.key();
        iter++;
        Partner *p =  partner.take(ip);
        ui->verticalLayout_3->removeWidget(p);
        delete p;
        p = nullptr;
    }

    //关闭传输音频
    disconnect(_ainput, SLOT(setVolumn(int)));
    disconnect(_aoutput, SLOT(setVolumn(int)));
    //关闭音频播放与采集
    _ainput->stopCollect();
    _aoutput->stopPlay();
    ui->openAudio->setText(QString(CLOSEAUDIO).toUtf8());
    ui->openAudio->setDisabled(true);

    //关闭图片传输线程
    if(_imgThread->isRunning()){
        _imgThread->quit();
        _imgThread->wait();
    }
    ui->openVideo->setText(QString(OPENVIDEO).toUtf8());
    ui->openVideo->setDisabled(true);
}

void Widget::paintEvent(QPaintEvent *event){
    Q_UNUSED(event);
    /*
     * 触发事件(3条， 一般使用第二条进行触发)
     * 1. 窗口部件第一次显示时，系统会自动产生一个绘图事件。从而强制绘制这个窗口部件，主窗口起来会绘制一次
     * 2. 当重新调整窗口部件的大小时，系统也会产生一个绘制事件--QWidget::update()或者QWidget::repaint()
     * 3. 当窗口部件被其它窗口部件遮挡，然后又再次显示出来时，就会对那些隐藏的区域产生一个绘制事件
    */
}

void Widget::on_createmeetBtn_clicked(){
    if(false == _createmeet){
        ui->createmeetBtn->setDisabled(true);
        ui->openAudio->setDisabled(true);
        ui->openVideo->setDisabled(true);
        ui->exitmeetBtn->setDisabled(true);
        emit PushText(CREATE_MEETING); //将 “创建会议"加入到发送队列
        WRITE_LOG("create meeting");
    }
}


void Widget::on_exitmeetBtn_clicked(){
    if(_captureSession->videoSink() != nullptr){
        _camera->stop();
    }

    ui->createmeetBtn->setDisabled(true);
    ui->exitmeetBtn->setDisabled(true);
    _createmeet = false;
    _joinmeet = false;
    //-----------------------------------------
    //清空partner
    clearPartner();
    // 关闭套接字

    //关闭socket
    _mytcpSocket->disconnectFromHost();
    _mytcpSocket->wait();

    ui->outlog->setText(tr("已退出会议"));

    ui->connServer->setDisabled(false);
    ui->groupBox_2->setTitle(QString("主屏幕"));
    //    ui->groupBox->setTitle(QString("副屏幕"));
    //清除聊天记录
    while(ui->listWidget->count() > 0)
    {
        QListWidgetItem *item = ui->listWidget->takeItem(0);
        ChatMessage *chat = (ChatMessage *) ui->listWidget->itemWidget(item);
        delete item;
        delete chat;
    }
    iplist.clear();
    ui->plainTextEdit->setCompleter(iplist);

    WRITE_LOG("exit meeting");

    QMessageBox::warning(this, "Information", "退出会议" , QMessageBox::Yes, QMessageBox::Yes);
}


void Widget::on_openVideo_clicked(){
    if(_captureSession->videoSink() != nullptr){
        _camera->stop();
        WRITE_LOG("close camera");
        if(_camera->error() == QCamera::NoError){
            _imgThread->quit();
            _imgThread->wait();
            ui->openVideo->setText("开启摄像头");
            emit PushText(CLOSE_CAMERA);
        }
        closeImg(_mytcpSocket->getlocalip());
    }else{
        _camera->start(); //开启摄像头
        WRITE_LOG("open camera");
        if(_camera->error() == QCamera::NoError)
        {
            _imgThread->start();
            ui->openVideo->setText("关闭摄像头");
        }
    }
}


void Widget::on_openAudio_clicked(){
    if (!_createmeet && !_joinmeet) return;
    if (ui->openAudio->text().toUtf8() == QString(OPENAUDIO).toUtf8()){
        emit startAudio();
        ui->openAudio->setText(QString(CLOSEAUDIO).toUtf8());
    }else if(ui->openAudio->text().toUtf8() == QString(CLOSEAUDIO).toUtf8()){
        emit stopAudio();
        ui->openAudio->setText(QString(OPENAUDIO).toUtf8());
    }
}


void Widget::on_connServer_clicked(){
    QString ip = ui->ip->text(), port = ui->port->text();
    ui->outlog->setText("正在连接到" + ip + ":" + port);
    repaint();

    QRegularExpression ipreg("((2{2}[0-3]|2[01][0-9]|1[0-9]{2}|0?[1-9][0-9]|0{0,2}[1-9])\\.)((25[0-5]|2[0-4][0-9]|[01]?[0-9]{0,2})\\.){2}(25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})");

    QRegularExpression portreg("^([0-9]|[1-9]\\d|[1-9]\\d{2}|[1-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$");
    QRegularExpressionValidator ipvalidate(ipreg), portvalidate(portreg);
    int pos = 0;
    if(ipvalidate.validate(ip, pos) != QValidator::Acceptable){
        QMessageBox::warning(this, "Input Error", "Ip Error", QMessageBox::Yes, QMessageBox::Yes);
        return;
    }
    if(portvalidate.validate(port, pos) != QValidator::Acceptable){
        QMessageBox::warning(this, "Input Error", "Port Error", QMessageBox::Yes, QMessageBox::Yes);
        return;
    }

    if(_mytcpSocket ->connectToServer(ip, port, QIODevice::ReadWrite)){
        ui->outlog->setText("成功连接到" + ip + ":" + port);
        ui->openAudio->setDisabled(true);
        ui->openVideo->setDisabled(true);
        ui->createmeetBtn->setDisabled(false);
        ui->exitmeetBtn->setDisabled(true);
        ui->joinmeetBtn->setDisabled(false);
        WRITE_LOG("succeeed connecting to %s:%s", ip.toStdString().c_str(), port.toStdString().c_str());
        QMessageBox::warning(this, "Connection success", "成功连接服务器" , QMessageBox::Yes, QMessageBox::Yes);
        ui->sendmsg->setDisabled(false);
        ui->connServer->setDisabled(true);
    }else{
        ui->outlog->setText("连接失败,请重新连接...");
        WRITE_LOG("failed to connenct %s:%s", ip.toStdString().c_str(), port.toStdString().c_str());
        QMessageBox::warning(this, "Connection error", _mytcpSocket->errorString() , QMessageBox::Yes, QMessageBox::Yes);
    }
}


void Widget::on_joinmeetBtn_clicked(){
    QString roomNo = ui->meetno->text();

    QRegularExpression roomreg("^[1-9][0-9]{1,4}$");
    QRegularExpressionValidator  roomvalidate(roomreg);
    int pos = 0;if(roomvalidate.validate(roomNo, pos) != QValidator::Acceptable){
        QMessageBox::warning(this, "RoomNo Error", "房间号不合法" , QMessageBox::Yes, QMessageBox::Yes);
    }
    else{
        //加入发送队列
        emit PushText(JOIN_MEETING, roomNo);
    }
}


void Widget::on_horizontalSliderAudio_valueChanged(int value){
    emit volumnChange(value);
}


void Widget::on_sendmsg_clicked()
{
    QString msg = ui->plainTextEdit->toPlainText().trimmed();
    if(msg.size() == 0)
    {
        qDebug() << "empty";
        return;
    }
    qDebug()<<msg;
    ui->plainTextEdit->setPlainText("");
    QString time = QString::number(QDateTime::currentSecsSinceEpoch());
    ChatMessage *message = new ChatMessage(ui->listWidget);
    QListWidgetItem *item = new QListWidgetItem();
    dealMessageTime(time);
    dealMessage(message, item, msg, time, QHostAddress(_mytcpSocket->getlocalip()).toString() ,ChatMessage::User_Me);
    emit PushText(TEXT_SEND, msg);
    ui->sendmsg->setDisabled(true);
}

